package com.syx.friend.Service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.syx.common.redis.Service.RedisService;
import com.syx.commoncore.Constant.CacheConstant;
import com.syx.commoncore.Constant.Constant;
import com.syx.commoncore.Model.Result;
import com.syx.commoncore.Model.TableDataInfoResult;
import com.syx.commoncore.Utils.ThreadLocalUtil;
import com.syx.friend.Manager.ExamCacheManager;
import com.syx.friend.Mapper.UserExamMapper;
import com.syx.friend.Model.exam.DTO.ExamQueryDTO;
import com.syx.friend.Model.exam.DTO.ExamRankDTO;
import com.syx.friend.Model.exam.VO.ExamListVO;
import com.syx.friend.Model.exam.VO.ExamRankVO;
import com.syx.friend.Model.exam.VO.ExamVO;
import com.syx.friend.Openfegin.FeignService;
import com.syx.friend.Service.IExamService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class IExamServiceImpl implements IExamService {

    @Resource
    UserExamMapper userExamMapper;

    @Resource
    FeignService feignService;

    @Resource
    ExamCacheManager examCacheManager;



    @Override
    public TableDataInfoResult list(ExamQueryDTO examQueryDTO) {
        // 调用 feignService 获取列表数据
        TableDataInfoResult list = feignService.list(examQueryDTO);
        List<?> rows = list.getRows();
        List<ExamListVO> examListVOList = new ArrayList<>();

        if (rows != null && !rows.isEmpty()) {
            for (Object row : rows) {
                try {
                    // 检查 row 对象是否有 status 属性且值为 1
                    if (row instanceof Map) {
                        Map<String, Object> rowMap = (Map<String, Object>) row;
                        Object statusObj = rowMap.get("status");
                        if (statusObj != null && statusObj instanceof Integer && (Integer) statusObj == 1) {
                            // 创建一个新的 ExamListVO 对象
                            ExamListVO examListVO = new ExamListVO();
                            // 将 row 对象的属性复制到 examListVO 对象中
                            BeanUtil.copyProperties(row, examListVO);
                            // 将 examListVO 对象添加到 examListVOList 列表中
                            examListVOList.add(examListVO);
                        }
                    } else {
                        // 如果 row 是实体类对象，通过反射获取 status 属性
                        java.lang.reflect.Field statusField = row.getClass().getDeclaredField("status");
                        statusField.setAccessible(true);
                        Object statusObj = statusField.get(row);
                        if (statusObj != null && statusObj instanceof Integer && (Integer) statusObj == 1) {
                            // 创建一个新的 ExamListVO 对象
                            ExamListVO examListVO = new ExamListVO();
                            // 将 row 对象的属性复制到 examListVO 对象中
                            BeanUtil.copyProperties(row, examListVO);
                            // 将 examListVO 对象添加到 examListVOList 列表中
                            examListVOList.add(examListVO);
                        }
                    }
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    // 处理反射过程中可能出现的异常
                    System.err.println("获取 status 属性失败: " + e.getMessage());

                    e.printStackTrace();
                } catch (Exception e) {
                    // 处理属性复制过程中可能出现的异常
                    System.err.println("属性复制失败: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        return TableDataInfoResult.success( examListVOList,examListVOList.size());
    }

    @Override
    public TableDataInfoResult redisList(ExamQueryDTO examQueryDTO) {
        if (examQueryDTO.getStartTime() != null && examQueryDTO.getEndTime() != null) {
            // 格式化日期时间
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime start = LocalDateTime.parse(examQueryDTO.getStartTime(), formatter);
            LocalDateTime end = LocalDateTime.parse(examQueryDTO.getEndTime(), formatter);

            // 获取全部数据
            TableDataInfoResult listResult = list(examQueryDTO);
            List<?> rows = listResult.getRows();
            List<ExamVO> filteredList = new ArrayList<>();

            if (rows != null && !rows.isEmpty()) {
                for (Object row : rows) {
                    try {
                        // 获取对象的 startTime 和 endTime 字段
                        Field startTimeField = row.getClass().getDeclaredField("startTime");
                        startTimeField.setAccessible(true);
                        Field endTimeField = row.getClass().getDeclaredField("endTime");
                        endTimeField.setAccessible(true);

                        // 获取字段值
                        Object startTimeObj = startTimeField.get(row);
                        Object endTimeObj = endTimeField.get(row);

                        if (startTimeObj instanceof LocalDateTime && endTimeObj instanceof LocalDateTime) {
                            LocalDateTime rowStartTime = (LocalDateTime) startTimeObj;
                            LocalDateTime rowEndTime = (LocalDateTime) endTimeObj;

                            // 判断时间范围
                            if (!rowStartTime.isBefore(start) &&!rowEndTime.isAfter(end)) {
                                ExamVO examVO = new ExamVO();
                                BeanUtil.copyProperties(row, examVO);
                                filteredList.add(examVO);
                            }
                        }
                    } catch (Exception e) {
                        System.err.println("过滤数据时发生异常: " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }

            return TableDataInfoResult.success(filteredList, filteredList.size());
        }

        else {
            //先在redis中查找数量，如果没有的话就去数据库中查
            Long listSize = examCacheManager.getListSize(examQueryDTO.getType(), null);
            //redis查不到的时候就在 数据库中查找
            if (listSize == null || listSize <= 0) {
                //如果没有数据就调用上面的方法进行查找，并且刷新到redis中
                TableDataInfoResult list = list(examQueryDTO);
                examCacheManager.refreshCache(examQueryDTO.getType(), null);
                List<ExamVO> examVOList = convertToExamVOList(list.getRows());
                assembleExamVoList(examVOList);
                return TableDataInfoResult.success(examVOList, new PageInfo<>(examVOList).getTotal());

            } else {
                List<ExamVO> examVOList = examCacheManager.getExamVOList(examQueryDTO, null);
                //
                examCacheManager.getListSize(examQueryDTO.getType(), null);
                if (CollectionUtil.isEmpty(examVOList)) {
                    return TableDataInfoResult.empty();
                }
                assembleExamVoList(examVOList);

                return TableDataInfoResult.success(examVOList, new PageInfo<>(examVOList).getTotal());

            }

        }


    }

    @Override
    public Result<String> getFirstQuestion(Long examId) {
        //先查缓存，再查数据库
        //获取该竞赛下题目的数量
        checkAndRefresh(examId);
        //这时候再从缓存中看没有就真的没有了
        return Result.success(examCacheManager.getFirstQuestion(examId).toString());


    }

    private void checkAndRefresh(Long examId) {
        Long examQuestionListSize = examCacheManager.getExamQuestionListSize(examId);
        if (examQuestionListSize==null || examQuestionListSize<=0){
            //可能没有同步，将竞赛下面的数据同步好
            examCacheManager.refreshExamQuestionCache(examId);
        }
    }

    @Override
    public Result<String> preQuestion(Long examId, Long questionId) {
        //先查缓存，再查数据库
        //获取该竞赛下题目的数量
        checkAndRefresh(examId);
        //这时候再从缓存中看没有就真的没有了
        return Result.success(examCacheManager.preQuestion(examId,questionId).toString());
    }

    @Override
    public Result<String> nextQuestion(Long examId, Long questionId) {
        checkAndRefresh(examId);
        //这时候再从缓存中看没有就真的没有了
        return Result.success(examCacheManager.nextQuestion(examId,questionId).toString());
    }



    @Override
    public TableDataInfoResult rankList(ExamRankDTO examRankDTO) {
        Long total = examCacheManager.getRankListSize(examRankDTO.getExamId());
        List<ExamRankVO> examRankVOList;
        if (total == null || total <= 0) {

            //只有在全空的情况下才会刷新
            PageHelper.startPage(examRankDTO.getPageNum(), examRankDTO.getPageSize());
            examRankVOList = userExamMapper.selectExamRankList(examRankDTO.getExamId());
            examCacheManager.refreshExamRankCache(examRankDTO.getExamId());
            total = new PageInfo<>(examRankVOList).getTotal();
        } else {
            examRankVOList = examCacheManager.getExamRankList(examRankDTO);
        }
        if (CollectionUtil.isEmpty(examRankVOList)) {
            return TableDataInfoResult.empty();
        }
        return TableDataInfoResult.success(examRankVOList, total);
    }

    //查看是否报名，传入所有的Exam，也有可能是游客登录
    public void assembleExamVoList(List<ExamVO> examVOList){
        Long userId= ThreadLocalUtil.get(Constant.USER_ID,Long.class);
        //获取用户已经报名的examId列表
        List<Long> userExamIdList=examCacheManager.getAllUserExamList(userId);
        if (CollectionUtil.isEmpty(userExamIdList)){
            return;
        }
        for (ExamVO examVO:examVOList){
            if (userExamIdList.contains(examVO.getExamId())){
                examVO.setEnter(true);
            }


        }


    }
    public List<ExamVO> convertToExamVOList(List<?> list) {

        if (list == null) {
            return Collections.emptyList();
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        return list.stream()
                .map(item -> {
                    try {
                        ExamVO vo = new ExamVO();

                        if (item instanceof Map) {
                            // 处理 Map 类型
                            Map<String, Object> map = (Map<String, Object>) item;
                            vo.setExamId(getLongValue(map, "examId"));
                            vo.setTitle(getStringValue(map, "title"));
                            vo.setStatus(getIntegerValue(map, "status"));
                            vo.setCreateBy(getStringValue(map, "createBy"));
                            vo.setCreateName(getStringValue(map, "createName"));
                            vo.setEnter(getBooleanValue(map, "enter", false));

                            vo.setStartTime(getLocalDateTimeValue(map, "startTime", formatter));
                            vo.setEndTime(getLocalDateTimeValue(map, "endTime", formatter));
                            vo.setCreateTime(getLocalDateTimeValue(map, "createTime", formatter));
                        }
                        else if (item != null) {
                            // 处理自定义对象类型（如 ExamListVO）
                            Class<?> clazz = item.getClass();

                            // 使用反射获取属性值
                            vo.setExamId(getFieldValue(clazz, item, "examId", Long.class));
                            vo.setTitle(getFieldValue(clazz, item, "title", String.class));
                            vo.setStatus(getFieldValue(clazz, item, "status", Integer.class));
                            vo.setCreateBy(getFieldValue(clazz, item, "createBy", String.class));
                            vo.setCreateName(getFieldValue(clazz, item, "createName", String.class));
                            vo.setEnter(getFieldValue(clazz, item, "enter", Boolean.class, false));

                            vo.setStartTime(getFieldValue(clazz, item, "startTime", LocalDateTime.class));
                            vo.setEndTime(getFieldValue(clazz, item, "endTime", LocalDateTime.class));
                            vo.setCreateTime(getFieldValue(clazz, item, "createTime", LocalDateTime.class));
                        }

                        return vo;
                    } catch (Exception e) {
                        log.error("Error converting item: {}", item, e);
                        return new ExamVO(); // 返回空对象，避免流处理中断
                    }
                })
                .collect(Collectors.toList());
    }
    private Field getField(Class<?> clazz, String fieldName) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (NoSuchFieldException e) {
            return null;
        }
    }

    // 反射辅助方法：获取字段值并转为 Long
    private Long getFieldValueAsLong(Object obj, Field field) {
        try {
            Object value = field.get(obj);
            if (value == null) return null;
            if (value instanceof Number) return ((Number) value).longValue();
            return Long.valueOf(value.toString());
        } catch (Exception e) {
            return null;
        }
    }

    // 反射辅助方法：获取字段值并转为 String
    private String getFieldValueAsString(Object obj, Field field) {
        try {
            Object value = field.get(obj);
            return value != null ? value.toString() : null;
        } catch (Exception e) {
            return null;
        }
    }

    // 反射辅助方法：获取字段值并转为 Integer
    private Integer getFieldValueAsInteger(Object obj, Field field) {
        try {
            Object value = field.get(obj);
            if (value == null) return null;
            if (value instanceof Number) return ((Number) value).intValue();
            return Integer.valueOf(value.toString());
        } catch (Exception e) {
            return null;
        }
    }

    // 反射辅助方法：获取字段值并转为 Boolean
    private Boolean getFieldValueAsBoolean(Object obj, Field field, boolean defaultValue) {
        try {
            Object value = field.get(obj);
            if (value == null) return defaultValue;
            if (value instanceof Boolean) return (Boolean) value;
            return Boolean.valueOf(value.toString());
        } catch (Exception e) {
            return defaultValue;
        }
    }

    // 反射辅助方法：获取字段值并转为 LocalDateTime
    private LocalDateTime getFieldValueAsLocalDateTime(Object obj, Field field, DateTimeFormatter formatter) {
        try {
            Object value = field.get(obj);
            if (value == null) return null;

            if (value instanceof LocalDateTime) {
                return (LocalDateTime) value;
            }

            if (value instanceof String) {
                return LocalDateTime.parse((String) value, formatter);
            }

            return null;
        } catch (Exception e) {
            return null;
        }
    }

    // 以下是之前的类型转换辅助方法（保持不变）


    private String getStringValue(Map<String, Object> row, String key) {
        Object value = row.get(key);
        return value != null ? value.toString() : null;
    }

    private Integer getIntegerValue(Map<String, Object> row, String key) {
        Object value = row.get(key);
        if (value == null) return null;
        if (value instanceof Number) return ((Number) value).intValue();
        try {
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private Boolean getBooleanValue(Map<String, Object> row, String key, boolean defaultValue) {
        Object value = row.get(key);
        if (value == null) return defaultValue;
        if (value instanceof Boolean) return (Boolean) value;
        return Boolean.parseBoolean(value.toString());
    }

    private LocalDateTime getLocalDateTimeValue(Map<String, Object> row, String key, DateTimeFormatter formatter) {
        Object value = row.get(key);
        if (value == null) return null;

        if (value instanceof LocalDateTime) {
            return (LocalDateTime) value;
        }

        if (value instanceof String) {
            try {
                return LocalDateTime.parse((String) value, formatter);
            } catch (Exception e) {
                return null;
            }
        }

        return null;
    }
    @SuppressWarnings("unchecked")
    private <T> T getFieldValue(Class<?> clazz, Object obj, String fieldName, Class<T> targetType) {
        return getFieldValue(clazz, obj, fieldName, targetType, null);
    }

    // 带默认值的通用反射获取字段值的方法
    @SuppressWarnings("unchecked")
    private <T> T getFieldValue(Class<?> clazz, Object obj, String fieldName, Class<T> targetType, T defaultValue) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            Object value = field.get(obj);

            if (value == null) {
                return defaultValue;
            }

            // 类型转换逻辑
            if (targetType.isAssignableFrom(value.getClass())) {
                return (T) value;
            }

            // 基本类型转换
            if (targetType == Long.class && value instanceof Number) {
                return (T) Long.valueOf(((Number) value).longValue());
            }

            if (targetType == Integer.class && value instanceof Number) {
                return (T) Integer.valueOf(((Number) value).intValue());
            }

            if (targetType == Boolean.class && value instanceof String) {
                return (T) Boolean.valueOf((String) value);
            }

            // 日期类型转换
            if (targetType == LocalDateTime.class && value instanceof String) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    return (T) LocalDateTime.parse((String) value, formatter);
                } catch (Exception e) {
                    return defaultValue;
                }
            }

            return defaultValue;
        } catch (Exception e) {
            return defaultValue;
        }
    }

    // 以下是 Map 处理的辅助方法（保持不变）
    private Long getLongValue(Map<String, Object> row, String key) {
        Object value = row.get(key);
        if (value == null) return null;
        if (value instanceof Number) return ((Number) value).longValue();
        try {
            return Long.parseLong(value.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }




}
